#include "MyMax7219Control.h"

// #define CLK 27
// #define CS 26
// #define DIN 25
#define NO_OPTION 0
#define D0 1
#define D1 2
#define D2 3
#define D3 4
#define D4 5
#define D5 6
#define D6 7
#define D7 8
#define DECODE_MODE 9
#define INTENSITY 10
#define SCAN_LIMIT 11
#define SHOUTDOWN 12
#define DISPLAY_TEST 15

// 宏定义选项

MyMax7219Control::MyMax7219Control(int CLK_PIN, int CS_PIN, int DIN_PIN) {
    CLK = CLK_PIN;
    CS = CS_PIN;
    DIN = DIN_PIN;

    pinMode(DIN, OUTPUT);
	pinMode(CS, OUTPUT);
	pinMode(CLK, OUTPUT);
	digitalWrite(CS, HIGH);
}

void MyMax7219Control::start() {
    // 将CS(片选)端置于低电平，此时可以写入数据
    digitalWrite(CS, LOW);
    // 将CLK端置于低电平，shiftin()/shiftout()要求调用时CLK端处于低电平
    digitalWrite(DIN, LOW);
}

void MyMax7219Control::end() {
    digitalWrite(CS, HIGH);
}

void MyMax7219Control::clear() {
    for (uint8_t i = 0; i < 8; i++)
    {
        insterDigit(i, 0);
    }
}

void MyMax7219Control::chooseMode(uint8_t mode, uint8_t data) {
    start();
    shiftOut(DIN, CLK, MSBFIRST, mode);
    shiftOut(DIN, CLK, MSBFIRST, data);
    end();
}

void MyMax7219Control::insterDigit(uint8_t digit, uint8_t data) {
    chooseMode((digit+1), data);
}

void MyMax7219Control::on() {
    clear();
    setDecodeMode(0);
    setIntensity(15);
    setScanLimit(7);
    isTestDisplay(0);
    chooseMode(SHOUTDOWN, 1);
}

void MyMax7219Control::off()
{
    chooseMode(SHOUTDOWN, 0);
}

void MyMax7219Control::printNum(int data)
{
    if (data >=10)
    {

        // clear
        insterDigit(3, 0);

        int units = data % 10;
        int tens = data / 10;
        for (uint8_t digit = 0; digit < 3; digit++)
        {
            insterDigit(digit, code[tens][digit]);
            insterDigit((digit + 4), code[units][digit]);
        }
        
    } else {
        // clear
        clear();
        for (uint8_t digit = 0; digit < 3; digit++)
        {
            insterDigit((digit+2), code[data][digit]);
        }
        
    }
}

void MyMax7219Control::isTestDisplay(uint8_t value) {
    chooseMode(DISPLAY_TEST, value);
}

void MyMax7219Control::setIntensity(uint8_t level) {
    chooseMode(INTENSITY, level);
}

void MyMax7219Control::setScanLimit(uint8_t limit) {
    chooseMode(SCAN_LIMIT, limit);
}

void MyMax7219Control::setDecodeMode(uint8_t mode) {
    chooseMode(DECODE_MODE, mode);
}

void MyMax7219Control::flxPoint(int point, uint8_t data) {

    for (int i = 0; i < 3; i++)
    {
        if ((point+i <=7) && (point+i >=0))
        {
            insterDigit(point+i, code[data][i]);
        }
    }
}

void MyMax7219Control::scrollNum(uint8_t num, float speed) {
    for (int flx = 7; flx > -4; flx--)
    {
            if (flx <= 4)
            {
                insterDigit(flx + 3, 0);
            }
        
        flxPoint(flx, num);
        
        delay(speed*1000);
    }
    
}


















